home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 4 / QRZ Ham Radio Callsign Database - Volume 4.iso / files / tcpip / amiga / asrc29p.lha / ax25cmd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-29  |  20.2 KB  |  954 lines

  1. /*
  2. ** FILE: ax25cmd.c
  3. **
  4. ** AX.25 command handler.
  5. **
  6. ** 09/24/90 Bob Applegate, wa2zzx
  7. **    Added BCTEXT, BC, and BCINTERVAL commands for broadcasting an id
  8. **    string using UI frames.
  9. */
  10.  
  11. #include <stdio.h>
  12. #include "global.h"
  13. #include "config.h"
  14. #include "mbuf.h"
  15. #include "timer.h"
  16. #include "proc.h"
  17. #include "iface.h"
  18. #include "ax25.h"
  19. #include "lapb.h"
  20. #include "cmdparse.h"
  21. #include "socket.h"
  22. #include "mailbox.h"
  23. #include "session.h"
  24. #include "tty.h"
  25. #include "nr4.h"
  26. #include "commands.h"
  27.  
  28. static int axhshort __ARGS((struct iface *ifp));
  29. static int axhlong __ARGS((struct iface *ifp));
  30. static void axflush __ARGS((struct iface *ifp));
  31. static int doaxfilter __ARGS((int argc,char *argv[],void *p));
  32. static int doaxflush __ARGS((int argc,char *argv[],void *p));
  33. static int doaxirtt __ARGS((int argc,char *argv[],void *p));
  34. static int doaxkick __ARGS((int argc,char *argv[],void *p));
  35. static int doaxreset __ARGS((int argc,char *argv[],void *p));
  36. static int doaxroute __ARGS((int argc,char *argv[],void *p));
  37. static int doaxstat __ARGS((int argc,char *argv[],void *p));
  38. static int doaxwindow __ARGS((int argc,char *argv[],void *p));
  39. static int dobc __ARGS((int argc,char *argv[],void *p));
  40. static int dobcint __ARGS((int argc,char *argv[],void *p));
  41. static int dobctext __ARGS((int argc,char *argv[],void *p));
  42. static int doblimit __ARGS((int argc,char *argv[],void *p));
  43. static int dodigipeat __ARGS((int argc,char *argv[],void *p));
  44. static int domaxframe __ARGS((int argc,char *argv[],void *p));
  45. static int domycall __ARGS((int argc,char *argv[],void *p));
  46. static int don2 __ARGS((int argc,char *argv[],void *p));
  47. static int dopaclen __ARGS((int argc,char *argv[],void *p));
  48. static int dopthresh __ARGS((int argc,char *argv[],void *p));
  49. static int doaxtype __ARGS((int argc,char *argv[],void *p));
  50. static int dot3 __ARGS((int argc,char *argv[],void *p));
  51. static int dot4 __ARGS((int argc,char *argv[],void *p));
  52. static int doversion __ARGS((int argc,char *argv[],void *p));
  53. static void ax_bc __ARGS((struct iface *axif));
  54. static int axdest __ARGS((struct iface *ifp));
  55. static int doaxautorec __ARGS((int argc,char *argv[],void *p));
  56. extern struct lq *al_lookup __ARGS((struct iface *ifp,char *addr,int sort));
  57.  
  58. static int Ax_autorec = 0;
  59. extern int axheard_filter_flag;        /* in axlink.c */
  60.  
  61. /* Default broadcast 'to' address in shifted ASCII */
  62. char ax_bcto[AXALEN] = {
  63.     'I'<<1, 'D'<<1, ' '<<1, ' '<<1, ' '<<1, ' '<<1, ('0'<<1) | E
  64. };
  65.  
  66. /* Defaults for IDing... */
  67. char *axbctext = NULL;    /* Text to send */
  68. static struct timer Broadtimer;    /* timer for broadcasts */
  69.  
  70. char *Ax25states[] = {
  71.     "",
  72.     "Disconnected",
  73.     "Listening",
  74.     "Conn pending",
  75.     "Disc pending",
  76.     "Connected",
  77.     "Recovery",
  78. };
  79.  
  80. /* Ascii explanations for the disconnect reasons
  81.    listed in lapb.h under "reason" in ax25_cb */
  82. char *Axreasons[] = {
  83.     "Normal",
  84.     "DM received",
  85.     "Timeout"
  86. };
  87.  
  88. static struct cmds Axcmds[] = {
  89.     "autorec",    doaxautorec,    0, 0, NULLCHAR,
  90.     "bc",        dobc,        0, 0, NULLCHAR,
  91.     "bcinterval",    dobcint,    0, 0, NULLCHAR,
  92.     "bctext",    dobctext,    0, 0, NULLCHAR,
  93.     "blimit",    doblimit,    0, 0, NULLCHAR,
  94.     "destlist",    doaxdest,    0, 0, NULLCHAR,
  95.     "digipeat",    dodigipeat,    0, 0, NULLCHAR,
  96.     "filter",    doaxfilter,    0, 0, NULLCHAR,
  97.     "flush",    doaxflush,    0, 0, NULLCHAR,
  98.     "irtt",        doaxirtt,    0, 0, NULLCHAR,
  99.     "kick",        doaxkick,    0, 2, "ax25 kick <axcb>",
  100.     "longheard",    doaxheard,    0, 0, NULLCHAR,
  101.     "maxframe",    domaxframe,    0, 0, NULLCHAR,
  102.     "mycall",    domycall,    0, 0, NULLCHAR,
  103.     "paclen",    dopaclen,    0, 0, NULLCHAR,
  104.     "pthresh",    dopthresh,    0, 0, NULLCHAR,
  105.     "reset",    doaxreset,    0, 2, "ax25 reset <axcb>",
  106.     "retry",    don2,        0, 0, NULLCHAR,
  107.     "route",    doaxroute,    0, 0, NULLCHAR,
  108.     "shortheard",    doaxheard,    0, 0, NULLCHAR,
  109.     "status",    doaxstat,    0, 0, NULLCHAR,
  110.     "t3",        dot3,        0, 0, NULLCHAR,
  111.     "t4",        dot4,        0, 0, NULLCHAR,
  112.     "timertype",    doaxtype,    0, 0, NULLCHAR,
  113.     "version",    doversion,    0, 0, NULLCHAR,
  114.     "window",    doaxwindow,    0, 0, NULLCHAR,
  115.     NULLCHAR,
  116. };
  117.  
  118. /* Multiplexer for top-level ax25 command */
  119. int
  120. doax25(argc,argv,p)
  121. int argc;
  122. char *argv[];
  123. void *p;
  124. {
  125.     if(argc == 1)
  126.         return doaxheard(argc,argv,p);
  127.     return subcmd(Axcmds,argc,argv,p);
  128. }
  129.  
  130. /* This function is called to send the current
  131.    broadcast message and reset the timer. */
  132. static int dobc(argc,argv,p)
  133. int argc;
  134. char *argv[];
  135. void *p;
  136. {
  137.     struct iface *ifa;
  138.  
  139.     if (argc < 2) {
  140.         tprintf("you need to specify an interface\n");
  141.         return 0;
  142.     }
  143.  
  144.     ifa = Ifaces;
  145.     while (ifa != NULL && stricmp(ifa->name,argv[1]))
  146.         ifa = ifa->next;
  147.     if (ifa == NULL)
  148.         tprintf(Badinterface, argv[1]);
  149.     else if (ifa->type != TYPE_AX25)
  150.         tprintf("not an AX.25 interface\n");
  151.     else {
  152.         ax_bc(ifa);
  153.         stop_timer(&Broadtimer) ;    /* in case it's already running */
  154.         start_timer(&Broadtimer);    /* and fire it up */
  155.     }
  156. }
  157.  
  158. /* View/Change the message we broadcast. */
  159. static int dobctext(argc,argv,p)
  160. int argc;
  161. char *argv[];
  162. void *p;
  163. {
  164.     if (argc < 2)
  165.         tprintf("Broadcast text:\n %s\n",axbctext);
  166.     else {
  167.         if (axbctext != NULL) free(axbctext);
  168.         axbctext = malloc(strlen(argv[1]));
  169.         strcpy(axbctext,argv[1]);
  170.     }
  171.     return 0;
  172. }
  173.  
  174. #define TICKSPERSEC    (1000L / MSPTICK)    /* Ticks per second */
  175.  
  176. /* Examine/change the broadcast interval. */
  177. static int dobcint(argc,argv,p)
  178. int argc;
  179. char *argv[];
  180. void *p;
  181. {
  182.     void dobroadtick();
  183.  
  184.     if(argc < 2) {
  185.         tprintf("Broadcast timer %lu/%lu seconds\n",
  186.             read_timer(&Broadtimer)/TICKSPERSEC,
  187.             dur_timer(&Broadtimer)/TICKSPERSEC);
  188.         return 0;
  189.     }
  190.     stop_timer(&Broadtimer) ;    /* in case it's already running */
  191.     Broadtimer.func = (void (*)())dobroadtick;/* what to call on timeout */
  192.     Broadtimer.arg = NULLCHAR;        /* dummy value */
  193.     Broadtimer.start = atoi(argv[1])*TICKSPERSEC;    /* set timer duration */
  194.     start_timer(&Broadtimer);        /* and fire it up */
  195.     return 0;
  196. }
  197.  
  198. void dobroadtick()
  199. {
  200.     struct iface *ifa;
  201.  
  202.     ifa = Ifaces;
  203.  
  204.     while (ifa != NULL) {
  205.         if (ifa->type == TYPE_AX25) ax_bc(ifa);
  206.         ifa = ifa->next;
  207.     }
  208.  
  209.     /* Restart timer */
  210.     start_timer(&Broadtimer) ;
  211. }
  212.  
  213. /* This is the low-level broadcast function. */
  214. static void ax_bc(axif)
  215. struct iface *axif;
  216. {
  217.     struct mbuf *hbp;
  218.     int16 i;
  219.  
  220.     /* prepare the header */
  221.     i = strlen(axbctext);
  222.     if((hbp = alloc_mbuf(i)) == NULLBUF)
  223.         return;
  224.  
  225.     hbp->cnt = i;
  226.     memcpy(hbp->data,axbctext,i);
  227.  
  228.     (*axif->output)(axif, ax_bcto, axif->hwaddr,
  229.         PID_NO_L3, hbp);    /* send it */
  230.  
  231.     /*
  232.     ** Call another function to reset the timer...
  233.     reset_bc_timer();
  234.     */
  235. }
  236.  
  237. int doaxheard(argc,argv,p)
  238. int argc;
  239. char *argv[];
  240. void *p;
  241. {
  242.     struct iface *ifp;
  243.  
  244.     if(argc > 1) {
  245.         if((ifp = if_lookup(argv[1])) == NULLIF) {
  246.             tprintf(Badinterface, argv[1]);
  247.             return 1;
  248.         }
  249.         if(ifp->output != ax_output) {
  250.             tprintf("Interface %s not AX.25\n",argv[1]);
  251.             return 1;
  252.         }
  253.         strncmp(argv[0],"l",1) ? axhshort(ifp) : axhlong(ifp);
  254.         return 0;
  255.     }
  256.     for(ifp = Ifaces;ifp != NULLIF;ifp = ifp->next) {
  257.         if(ifp->output != ax_output)
  258.             continue;    /* Not an ax.25 interface */
  259.         strncmp(argv[0],"l",1) ? axhshort(ifp) : axhlong(ifp);
  260.     }
  261.     return 0;
  262. }
  263.  
  264. static int axhshort(ifp)
  265. struct iface *ifp;
  266. {
  267.     int col = 0;
  268.     struct lq *lp;
  269.     char tmp[AXBUF];
  270.  
  271.     if(ifp->hwaddr == NULLCHAR)
  272.         return 0;
  273.  
  274.     tprintf("Interface  Station   Time since send  Pkts sent\n");
  275.     tprintf("%-9s  %-9s   %12s    %7lu\n",
  276.         ifp->name, pax25(tmp,ifp->hwaddr),
  277.         tformat(Clock - ifp->lastsent),
  278.         ifp->rawsndcnt);
  279.     tprintf("Station   Last Heard     Pkts    "
  280.         "Station   Last Heard     Pkts\n");
  281.     for(lp = Lq;lp != NULLLQ;lp = lp->next) {
  282.         if(lp->iface != ifp)
  283.             continue;
  284.         if(col)
  285.             tprintf("    ");
  286.         tprintf("%-9s %10s %8lu",
  287.             pax25(tmp,lp->addr),
  288.             tformat(Clock - lp->time),
  289.             lp->currxcnt);
  290.         if(col) {
  291.             if(tprintf("\n") == EOF) {
  292.                 return EOF;
  293.             } else col = 0;
  294.         } else col = 1;
  295.     }
  296.     if(col)
  297.         tprintf("\n");
  298.  
  299.     return 0;
  300. }
  301.  
  302. static int axhlong(ifp)
  303. struct iface *ifp;
  304. {
  305.     struct lq *lp;
  306.     char tmp[AXBUF];
  307.  
  308.     if(ifp->hwaddr == NULLCHAR)
  309.         return 0;
  310.  
  311.     tprintf("Interface  Station   Time since send  Pkts sent\n");
  312.     tprintf("%-9s  %-9s   %12s    %7lu\n",ifp->name,pax25(tmp,ifp->hwaddr),
  313.      tformat(Clock - ifp->lastsent),ifp->rawsndcnt);
  314.     tprintf("Station   Last Heard"
  315.         "     UI     I SABM   UA   RR  REJ   DM DISC"
  316.         " FRMR  RNR   ??\n");
  317.     for(lp = Lq;lp != NULLLQ;lp = lp->next) {
  318.         if(lp->iface != ifp)
  319.             continue;
  320.         tprintf("%-9s %10s"
  321.             "  %5lu %5lu %4lu %4lu %4lu %4lu %4lu %4lu"
  322.             " %4lu %4lu %4lu\n",
  323.             pax25(tmp,lp->addr), tformat(Clock - lp->time),
  324.             lp->ui, lp->i, lp->sabm, lp->ua, lp->rr, lp->rej,
  325.             lp->dm, lp->disc, lp->frmr, lp->rnr, lp->invalid);
  326.     }
  327.  
  328.     return 0;
  329. }
  330.  
  331. int doaxdest(argc,argv,p)
  332. int argc;
  333. char *argv[];
  334. void *p;
  335. {
  336.     struct iface *ifp;
  337.  
  338.     if(argc > 1){
  339.         if((ifp = if_lookup(argv[1])) == NULLIF){
  340.             tprintf(Badinterface,argv[1]);
  341.             return 1;
  342.         }
  343.         if(ifp->output != ax_output){
  344.             tprintf("Interface %s not AX.25\n",argv[1]);
  345.             return 1;
  346.         }
  347.         axdest(ifp);
  348.         return 0;
  349.     }
  350.     for(ifp = Ifaces;ifp != NULLIF;ifp = ifp->next){
  351.         if(ifp->output != ax_output)
  352.             continue;    /* Not an ax.25 interface */
  353.         if(axdest(ifp) == EOF)
  354.             break;
  355.     }
  356.     return 0;
  357. }
  358.  
  359. static int axdest(ifp)
  360. struct iface *ifp;
  361. {
  362.     int col = 0;
  363.     struct ld *lp;
  364.     struct lq *lq;
  365.     char tmp[AXBUF];
  366.  
  367.     if(ifp->hwaddr == NULLCHAR)
  368.         return 0;
  369.     tprintf("%s:\n",ifp->name);
  370.     tprintf("Station    Last ref  Last heard   Pkts  "
  371.         "Station    Last ref  Last heard   Pkts\n");
  372.     for(lp = Ld;lp != NULLLD;lp = lp->next){
  373.         if(lp->iface != ifp)
  374.             continue;
  375.         if(col)
  376.             tprintf("  ");
  377.         tprintf("%-9s %10s",
  378.             pax25(tmp,lp->addr),
  379.             tformat(Clock - lp->time));
  380.  
  381.         if(addreq(lp->addr,ifp->hwaddr)){
  382.             /* Special case; it's our address */
  383.             tprintf(" %10s",tformat(Clock - ifp->lastsent));
  384.         } else if((lq = al_lookup(ifp,lp->addr,0)) == NULLLQ){
  385.             tprintf(" %10s","");
  386.         } else {
  387.             tprintf(" %10s",tformat(Clock - lq->time));
  388.         }
  389.         tprintf(" %6lu",lp->currxcnt);
  390.         if(col) {
  391.             if(tprintf("\n") == EOF) {
  392.                 return EOF;
  393.             } else col = 0;
  394.         } else col = 1;
  395.     }
  396.     if(col)
  397.         tprintf("\n");
  398.  
  399.     return 0;
  400. }
  401.  
  402. static int doaxfilter(argc,argv,p)
  403. int argc;
  404. char *argv[];
  405. void *p;
  406. {
  407.     if(argc >= 2){
  408.         setint(&axheard_filter_flag,"ax25 heard filter",argc,argv);
  409.     } else {
  410.         tprintf("Usage: ax25 filter <0|1|2|3>\n");
  411.         return 1;
  412.     }
  413.  
  414.     tprintf("Callsign logging by source ");
  415.     if(axheard_filter_flag & AXHEARD_NOSRC)
  416.         tprintf("disabled, ");
  417.     else
  418.         tprintf("enabled, ");
  419.     tprintf("by destination ");
  420.     if(axheard_filter_flag & AXHEARD_NODST)
  421.         tprintf("disabled\n");
  422.     else
  423.         tprintf("enabled\n");
  424.     return 0;
  425. }
  426.  
  427. static int doaxflush(argc,argv,p)
  428. int argc;
  429. char *argv[];
  430. void *p;
  431. {
  432.     struct iface *ifp;
  433.  
  434.     for(ifp = Ifaces;ifp != NULLIF;ifp = ifp->next){
  435.         if(ifp->output != ax_output)
  436.             continue;    /* Not an ax.25 interface */
  437.         axflush(ifp);
  438.     }
  439.     return 0;
  440. }
  441.  
  442. static void axflush(ifp)
  443. struct iface *ifp;
  444. {
  445.     struct lq *lp,*lp1;
  446.     struct ld *ld,*ld1;
  447.  
  448.     ifp->rawsndcnt = 0;
  449.     for(lp = Lq;lp != NULLLQ;lp = lp1){
  450.         lp1 = lp->next;
  451.         free((char *)lp);
  452.     }
  453.     Lq = NULLLQ;
  454.  
  455.     for(ld = Ld;ld != NULLLD;ld = ld1){
  456.         ld1 = ld->next;
  457.         free((char *)ld);
  458.     }
  459.     Ld = NULLLD;
  460. }
  461.  
  462. static doaxreset(argc,argv,p)
  463. int argc;
  464. char *argv[];
  465. void *p;
  466. {
  467.     struct ax25_cb *axp;
  468.  
  469.     axp = (struct ax25_cb *)ltop(htol(argv[1]));
  470.     if(!ax25val(axp)){
  471.         tprintf(Notval);
  472.         return 1;
  473.     }
  474.     reset_ax25(axp);
  475.     return 0;
  476. }
  477.  
  478. /* Display AX.25 link level control blocks */
  479. static doaxstat(argc,argv,p)
  480. int argc;
  481. char *argv[];
  482. void *p;
  483. {
  484.     register int i;
  485.     register struct ax25_cb *axp;
  486.     char tmp[AXBUF];
  487.  
  488.     if(argc < 2){
  489.         tprintf("    &AXB Snd-Q   Rcv-Q   Remote    State\n");
  490.         for(i=0;i<NHASH;i++){
  491.             for(axp = Ax25_cb[i];axp != NULLAX25; axp = axp->next){
  492.  
  493.                 if(tprintf("%8lx %-8d%-8d%-10s%s\n",
  494.                     ptol(axp),
  495.                     len_q(axp->txq),len_p(axp->rxq),
  496.                     pax25(tmp,axp->remote),
  497.                     Ax25states[axp->state]) == EOF)
  498.                         return 0;
  499.             }
  500.         }
  501.         return 0;
  502.     }
  503.     axp = (struct ax25_cb *)ltop(htol(argv[1]));
  504.     if(!ax25val(axp)){
  505.         tprintf(Notval);
  506.         return 1;
  507.     }
  508.     st_ax25(axp);
  509.     return 0;
  510. }
  511.  
  512. /* Dump one control block */
  513. void st_ax25(axp)
  514. register struct ax25_cb *axp;
  515. {
  516.     char tmp[AXBUF];
  517.  
  518.     if(axp == NULLAX25)
  519.         return;
  520.     tprintf("    &AXB Remote   RB V(S) V(R) Unack P Retry State\n");
  521.  
  522.     tprintf("%8lx %-9s%c%c",ptol(axp),pax25(tmp,axp->remote),
  523.      axp->flags.rejsent ? 'R' : ' ',
  524.      axp->flags.remotebusy ? 'B' : ' ');
  525.     tprintf(" %4d %4d",axp->vs,axp->vr);
  526.     tprintf(" %02u/%02u %u",axp->unack,axp->maxframe,axp->proto);
  527.     tprintf(" %02u/%02u",axp->retries,axp->n2);
  528.     tprintf(" %s\n",Ax25states[axp->state]);
  529.  
  530.     tprintf("SRTT = %lu MDEV = %lu ",axp->srt,axp->mdev);
  531.     tprintf("T1: ");
  532.     if(run_timer(&axp->t1))
  533.         tprintf("%lu",read_timer(&axp->t1) * MSPTICK);
  534.     else
  535.         tprintf("stop");
  536.     tprintf("/%lu ms; ",dur_timer(&axp->t1) * MSPTICK);
  537.  
  538.     tprintf("T3: ");
  539.     if(run_timer(&axp->t3))
  540.         tprintf("%lu",read_timer(&axp->t3) * MSPTICK);
  541.     else
  542.         tprintf("stop");
  543.     tprintf("/%lu ms; ",dur_timer(&axp->t3) * MSPTICK);
  544.  
  545.     tprintf("T4: ");
  546.     if(run_timer(&axp->t4))
  547.         tprintf("%lu",(read_timer(&axp->t4) * MSPTICK) / 1000);
  548.     else
  549.         tprintf("stop");
  550.     tprintf("/%lu sec\n",(dur_timer(&axp->t4) * MSPTICK) / 1000);
  551. }
  552.  
  553. /* Display or change our AX.25 address */
  554. static domycall(argc,argv,p)
  555. int argc;
  556. char *argv[];
  557. void *p;
  558. {
  559.     char tmp[AXBUF];
  560.  
  561.     if(argc < 2){
  562.         tprintf("%s\n",pax25(tmp,Mycall));
  563.         return 0;
  564.     }
  565.     if(setcall(Mycall,argv[1]) == -1)
  566.         return -1;
  567.     return 0;
  568. }
  569.  
  570. /* Control AX.25 digipeating */
  571. static dodigipeat(argc,argv,p)
  572. int argc;
  573. char *argv[];
  574. void *p;
  575. {
  576.     return setbool(&Digipeat,"Digipeat",argc,argv);
  577. }
  578.  
  579. /* Set limit on retransmission backoff */
  580. static doblimit(argc,argv,p)
  581. int argc;
  582. char *argv[];
  583. void *p;
  584. {
  585.     return setlong(&Blimit,"blimit",argc,argv);
  586. }
  587.  
  588. static doversion(argc,argv,p)
  589. int argc;
  590. char *argv[];
  591. void *p;
  592. {
  593.     return setshort(&Axversion,"AX25 version",argc,argv);
  594. }
  595.  
  596. static doaxirtt(argc,argv,p)
  597. int argc;
  598. char *argv[];
  599. void *p;
  600. {
  601.     return setlong(&Axirtt,"Initial RTT (ms)",argc,argv);
  602. }
  603.  
  604. /* Set idle timer */
  605. static dot3(argc,argv,p)
  606. int argc;
  607. char *argv[];
  608. void *p;
  609. {
  610.     return setlong(&T3init,"Idle poll timer (ms)",argc,argv);
  611. }
  612.  
  613. /* Set link redundancy timer */
  614. static dot4(argc,argv,p)
  615. int argc;
  616. char *argv[];
  617. void *p;
  618. {
  619.     return setlong(&T4init,"Link redundancy timer (sec)",argc,argv);
  620. }
  621.  
  622. /* Set retry limit count */
  623. static don2(argc,argv,p)
  624. int argc;
  625. char *argv[];
  626. void *p;
  627. {
  628.     return setshort(&N2,"Retry limit",argc,argv);
  629. }
  630.  
  631. /* Force a retransmission */
  632. static doaxkick(argc,argv,p)
  633. int argc;
  634. char *argv[];
  635. void *p;
  636. {
  637.     struct ax25_cb *axp;
  638.  
  639.     axp = (struct ax25_cb *)ltop(htol(argv[1]));
  640.     if(!ax25val(axp)){
  641.         tprintf(Notval);
  642.         return 1;
  643.     }
  644.     kick_ax25(axp);
  645.     return 0;
  646. }
  647.  
  648. /* Set maximum number of frames that will be allowed in flight */
  649. static domaxframe(argc,argv,p)
  650. int argc;
  651. char *argv[];
  652. void *p;
  653. {
  654.     return setshort(&Maxframe,"Window size (frames)",argc,argv);
  655. }
  656.  
  657. /* Set maximum length of I-frame data field */
  658. static dopaclen(argc,argv,p)
  659. int argc;
  660. char *argv[];
  661. void *p;
  662. {
  663.     return setshort(&Paclen,"Max frame length (bytes)",argc,argv);
  664. }
  665.  
  666. /* Set size of I-frame above which polls will be sent after a timeout */
  667. static dopthresh(argc,argv,p)
  668. int argc;
  669. char *argv[];
  670. void *p;
  671. {
  672.     return setshort(&Pthresh,"Poll threshold (bytes)",argc,argv);
  673. }
  674.  
  675. /* Set high water mark on receive queue that triggers RNR */
  676. static doaxwindow(argc,argv,p)
  677. int argc;
  678. char *argv[];
  679. void *p;
  680. {
  681.     return setshort(&Axwindow,"AX25 receive window (bytes)",argc,argv);
  682. }
  683. /* End of ax25 subcommands */
  684.  
  685. static int doaxautorec(argc,argv,p)
  686. int argc ;
  687. char *argv[] ;
  688. void *p;
  689. {
  690.     return setbool(&Ax_autorec,"AX-AutoRecord flag",argc,argv);
  691. }
  692.  
  693. /* Initiate interactive AX.25 connect to remote station */
  694. int doconnect(argc,argv,p)
  695. int argc;
  696. char *argv[];
  697. void *p;
  698. {
  699.     struct sockaddr_ax fsocket;
  700.     struct session *sp;
  701.     int ndigis,i;
  702.     char digis[MAXDIGIS][AXALEN];
  703.     char target[AXALEN];
  704.     int split = 0;
  705.  
  706.     if(setcall(target,argv[2]) == -1){
  707.         tprintf("Bad callsign %s\n", argv[2]);
  708.         return 1;
  709.     }
  710.  
  711.     /* If digipeaters are given, put them in the routing table */
  712.     if(argc > 3){
  713.         if(setcall(target,argv[2]) == -1){
  714.             tprintf("Bad callsign %s\n", argv[2]);
  715.             return 1;
  716.         }
  717.         ndigis = argc - 3;
  718.         if(ndigis > MAXDIGIS){
  719.             tprintf("Too many digipeaters\n");
  720.             return 1;
  721.         }
  722.         for(i=0;i<ndigis;i++){
  723.             if(setcall(digis[i],argv[i+3]) == -1){
  724.                 tprintf("Bad digipeater %s\n",argv[i+3]);
  725.                 return 1;
  726.             }
  727.         }
  728.         if(ax_add(target,AX_LOCAL,digis,ndigis) == NULLAXR){
  729.             tprintf("Route add failed\n");
  730.             return 1;
  731.         }
  732.     }
  733.     /* Allocate a session descriptor */
  734.     if((sp = newsession(argv[2],AX25TNC,split)) == NULLSESSION){
  735.         tprintf("Too many sessions\n");
  736.         return 1;
  737.     }
  738.     if((sp->s = socket(AF_AX25,SOCK_STREAM,0)) == -1){
  739.         tprintf("Can't create socket\n");
  740.         freesession(sp);
  741.         keywait(NULLCHAR,1);
  742.         return 1;
  743.     }
  744.     fsocket.sax_family = AF_AX25;
  745.     setcall(fsocket.ax25_addr,argv[2]);
  746.     strncpy(fsocket.iface,argv[1],ILEN);
  747.  
  748.     if(Ax_autorec)
  749.         if((sp->record = fopen(argv[2],APPEND_TEXT)) == NULLFILE)
  750.             tprintf("Can't open %s: %s\n",argv[2],sys_errlist[errno]);
  751.         else
  752.             sp->rfile = strdup(argv[2]);
  753.  
  754.     return tel_connect(sp, (char *)&fsocket, sizeof(struct sockaddr_ax));
  755. }
  756.  
  757. /* Display and modify AX.25 routing table */
  758. static int doaxroute(argc,argv,p)
  759. int argc;
  760. char *argv[];
  761. void *p;
  762. {
  763.     char tmp[AXBUF];
  764.     int i,j,ndigis;
  765.     register struct ax_route *axr;
  766.     char target[AXALEN],digis[MAXDIGIS][AXALEN];
  767.  
  768.     if(argc < 2){
  769.         tprintf("Target    Type  Mode Digipeaters\n");
  770.         for(i=0;i<NHASH;i++){
  771.             for(axr = Ax_routes[i];axr != NULLAXR;axr = axr->next){
  772.                 tprintf("%-10s%-6s",pax25(tmp,axr->target),
  773.                     axr->type == AX_LOCAL ? "Local":"Auto");
  774.                 switch(axr->mode){
  775.                 case AX_VC_MODE:
  776.                     tprintf(" VC ");
  777.                     break;
  778.                 case AX_DATMODE:
  779.                     tprintf(" DG ");
  780.                     break;
  781.                 case AX_DEFMODE:
  782.                     tprintf(" IF ");
  783.                     break;
  784.                 default:
  785.                     tprintf(" ?? ");
  786.                     break;
  787.                 }
  788.                 for(j=0;j<axr->ndigis;j++){
  789.                     tprintf(" %s",pax25(tmp,axr->digis[j]));
  790.                 }
  791.                 if(tprintf("\n") == EOF)
  792.                     return 0;
  793.             }
  794.         }
  795.         return 0;
  796.     }
  797.     if(argc < 3){
  798.         tprintf("Usage: ax25 route add <target> [digis...]\n");
  799.         tprintf("       ax25 route drop <target>\n");
  800.         tprintf("       ax25 route mode <target> [mode]\n");
  801.         return 1;
  802.     }
  803.     if(setcall(target,argv[2]) == -1){
  804.         tprintf("Bad target %s\n",argv[2]);
  805.         return 1;
  806.     }
  807.     switch(argv[1][0]){
  808.     case 'a':    /* Add route */
  809.         ndigis = argc - 3;
  810.         if(ndigis > MAXDIGIS){
  811.             tprintf("Too many digipeaters\n");
  812.             return 1;
  813.         }
  814.         for(i=0;i<ndigis;i++){
  815.             if(setcall(digis[i],argv[i+3]) == -1){
  816.                 tprintf("Bad digipeater %s\n",argv[i+3]);
  817.                 return 1;
  818.             }
  819.         }
  820.         if(ax_add(target,AX_LOCAL,digis,ndigis) == NULLAXR){
  821.             tprintf("Failed\n");
  822.             return 1;
  823.         }
  824.         break;
  825.     case 'd':    /* Drop route */
  826.         if(ax_drop(target) == -1){
  827.             tprintf("Not in table\n");
  828.             return 1;
  829.         }
  830.         break;
  831.     case 'm':    /* Alter route mode */
  832.         if(argc < 4){
  833.             tprintf("Usage: ax25 route mode <target> <mode>\n");
  834.             tprintf("Where mode is 'vc', 'datagram' or 'interface'\n");
  835.             return 1;
  836.         }
  837.         if((axr = ax_lookup(target)) == NULLAXR){
  838.             tprintf("Not in table\n");
  839.             return 1;
  840.         }
  841.         switch(argv[3][0]){
  842.         case 'i':    /* use default interface mode */
  843.             axr->mode = AX_DEFMODE;
  844.             break;
  845.         case 'v':    /* use virtual circuit mode */
  846.             axr->mode = AX_VC_MODE;
  847.             break;
  848.         case 'd':    /* use datagram mode */
  849.             axr->mode = AX_DATMODE;
  850.             break;
  851.         default:
  852.             tprintf("Unknown mode %s\n", argv[3]);
  853.             return 1;
  854.         }
  855.         break;
  856.     default:
  857.         tprintf("Unknown command %s\n",argv[1]);
  858.         return 1;
  859.     }
  860.     return 0;
  861. }
  862.  
  863. #ifdef    MAILBOX
  864. int ax25start(argc,argv,p)
  865. int argc;
  866. char *argv[];
  867. void *p;
  868. {
  869.     int s,type;
  870.  
  871.     freeargs(argc,argv);    /* Args are not used */
  872.     if (Axi_sock != -1)
  873.         return 0;
  874.  
  875.     psignal(Curproc,0);    /* Don't keep the parser waiting */
  876.     chname(Curproc,"AX25 listener");
  877.     Axi_sock = socket(AF_AX25,SOCK_STREAM,0);
  878.     /* bind() is done automatically */
  879.     if(listen(Axi_sock,1) == -1){
  880.         close_s(Axi_sock);
  881.         return -1;
  882.     }
  883.     for(;;){
  884.         if((s = accept(Axi_sock,NULLCHAR,NULLINT)) == -1)
  885.             break;    /* Service is shutting down */
  886.  
  887.         type = AX25TNC;
  888.         /* Eat the line that triggered the connection
  889.          * and then start the mailbox
  890.          */
  891.         recvline(s,NULLCHAR,80); 
  892.         newproc("mbox",2048,mbx_incom,s,(void *)&type,NULL);
  893.     }
  894.     close_s(Axi_sock);
  895.     Axi_sock = -1;
  896.     return 0;
  897. }
  898.  
  899. int ax250(argc,argv,p)
  900. int argc;
  901. char *argv[];
  902. void *p;
  903. {
  904.     close_s(Axi_sock);
  905.     Axi_sock = -1;
  906.     return 0;
  907. }
  908. #endif
  909.  
  910. /* ax25 timers type - linear v exponential */
  911. static doaxtype(argc,argv,p)
  912. int argc ;
  913. char *argv[] ;
  914. void *p ;
  915. {
  916.     extern unsigned lapbtimertype;
  917.  
  918.     if (argc < 2) {
  919.         tprintf("AX25 timer type is ");
  920.         switch(lapbtimertype){
  921.         case 2:
  922.             tprintf("original\n");
  923.             break;
  924.         case 1:
  925.             tprintf("linear\n");
  926.             break;
  927.         case 0:
  928.             tprintf("exponential\n");
  929.             break;
  930.         }
  931.         return 0 ;
  932.     }
  933.     
  934.     switch (argv[1][0]) {
  935.         case 'o':
  936.         case 'O':
  937.             lapbtimertype = 2 ;
  938.             break ;
  939.         case 'l':
  940.         case 'L':
  941.             lapbtimertype = 1 ;
  942.             break ;
  943.         case 'e':
  944.         case 'E':
  945.             lapbtimertype = 0 ;
  946.             break ;
  947.         default:
  948.             tprintf("use: ax25 timertype [original|linear|exponential]\n") ;
  949.             return -1 ;
  950.     }
  951.  
  952.     return 0 ;
  953. }
  954.